package servlets;

import java.io.IOException;
import java.util.ArrayList;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import bean.AuctionItemBean;
import bean.BidBean;
import dao.AuctionItemDAO;
import dao.BidDAO;

/**
 * Servlet implementation class AuctionItemServlet
 * 
 * @author Sander Meijer & Stijn Kliemesch
 */
public class AuctionItemServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	/**
	 * @see HttpServlet#HttpServlet()
	 */
	public AuctionItemServlet() {
		super();
	}

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 * Used for searching for an auction, going to an auction item page or to the edit page of an auction item
	 * Requires parameter "action" with one of the following values:
	 * -"search"
	 * -"GoToAuction"
	 * -"doGoToEdit"
	 */
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		if ((Boolean) request.getSession().getAttribute("loggedIn")) {
			String action = request.getParameter("action");
			if (action.equals("search")) {
				handleSearch(request, response);
			} else if (action.equals("GoToAuction")) {
				handleGoTo(request, response);
			} else if (action.equals("doGoToEdit")) {
				handleGoToEdit(request, response);
			}
		}
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
	 *      response)
	 * Used for deleting an auction item, creating a new one, bidding on an auction item or editing an auction item
	 * Requires parameter "action" with one of the following values:
	 * -"delete"
	 * -"newAuction"
	 * -"bid"
	 * -"doEdit"
	 */
	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		if ((Boolean) request.getSession().getAttribute("loggedIn")) {
			String action = request.getParameter("action");
			// System.out.println(action);
			if (action.equals("delete")) {
				handleDelete(request, response);
			} else if (action.equals("newAuction")) {
				handleNewAuction(request, response);
			} else if (action.equals("bid")) {
				handleNewBid(request, response);
			} else if (action.equals("doEdit")) {
				handleEdit(request, response);
			}
		}
	}

	/**
	 * Handles searches
	 * 
	 * @param request
	 * @param response
	 * @throws ServletException
	 * @throws IOException
	 */
	private void handleSearch(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		String searchTerm = request.getParameter("searchTerm");
		String searchTarget = request.getParameter("searchTarget");
		RequestDispatcher dispatcher = null;
		ArrayList<AuctionItemBean> searchedBeans = null;
		String url = "";
		int userID = (Integer) request.getSession().getAttribute("userID");
		
		//Decide which type of search should be performed
		if (searchTarget.equals("auctions")) { // Handle auctions
			if (searchTerm.length() > 0) {
				searchedBeans = AuctionItemDAO.getSearchedAuctions(searchTerm);
				url = "/WEB-INF/auctions.jsp";
			}
		} else if (searchTarget.equals("my-auctions")) { // Handle my auctions
			searchedBeans = AuctionItemDAO.getAuctionsByOwnerIDAndSearch(userID, searchTerm);
			url = "/WEB-INF/my-auctions.jsp";
		} else if (searchTarget.equals("my-bids")) { // Handle bids
			searchedBeans = AuctionItemDAO.getAuctionsWithBidsFromUserIDdAndSearch(userID,searchTerm);
			for (AuctionItemBean AIB : searchedBeans) {
				AIB.setYourTopBid(getTopBidOfOwnerFromAuctionItem(AIB, userID));
			}
			url = "/WEB-INF/my-bids.jsp";
		}
		if(searchedBeans != null) {
			request.setAttribute("searchedBeans", searchedBeans);
			dispatcher = request.getRequestDispatcher(response.encodeURL(url));
			dispatcher.forward(request, response);
		}
	}

	/**
	 * Handles the goTo request, redirecting the page to given auction Item page
	 * 
	 * @param request
	 * @param response
	 * @throws ServletException
	 * @throws IOException
	 */
	private void handleGoTo(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		try {
			int auctionItemID = Integer.parseInt(request.getParameter("auctionItemID"));

			AuctionItemBean goToBean = AuctionItemDAO.getAuctionByID(auctionItemID);
			goToBean.setYourTopBid(getTopBidOfOwnerFromAuctionItem(goToBean, (Integer) request.getSession().getAttribute("userID")));
			
			request.setAttribute("goToBean", goToBean);
			RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/auction-item.jsp");
			dispatcher.forward(request, response);
		} catch (NumberFormatException e) {
			e.printStackTrace();
		}
	}

	/**
	 * makes the page have the rights attributes and redirects it to the edit
	 * page.
	 * 
	 * @param request
	 * @param response
	 * @throws ServletException
	 * @throws IOException
	 */
	private void handleGoToEdit(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {

		int auctionItemID = Integer.parseInt(request.getParameter("auctionItemID"));
		AuctionItemBean goToEditBean = AuctionItemDAO.getAuctionByID(auctionItemID);

		request.setAttribute("titleName", goToEditBean.getTitle());
		request.setAttribute("description", goToEditBean.getDescription());
		request.setAttribute("auctionItemID", auctionItemID);

		RequestDispatcher dispatcher = request.getRequestDispatcher(response.encodeURL("/WEB-INF/auction-edit.jsp"));
		dispatcher.forward(request, response);
	}

	/**
	 * Handles a new bid
	 * 
	 * @param request
	 * @param response
	 * @throws ServletException
	 * @throws IOException
	 */
	private void handleNewBid(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {

		RequestDispatcher dispatcher = null;
		int auctionItemID = Integer.parseInt(request
				.getParameter("auctionItemID"));
		int userID = (Integer) request.getSession().getAttribute("userID");
		AuctionItemBean AIB = AuctionItemDAO.getAuctionByID(auctionItemID);

		String url = "/WEB-INF/auction-item.jsp";

		if (AIB != null) {
			if (userID == AIB.getTopBid().getBidUserID()) {
				request.setAttribute("goToBean", AIB);
				dispatcher = request.getRequestDispatcher(url);
			}
			int bidValue = -1;
			try {
				bidValue = Integer.parseInt(request.getParameter("bidValue"));
				if (bidValue > AIB.getStartPrice()) {
					if(AIB.getTopBid() != null){
						if(bidValue > AIB.getTopBid().getBidValue() ){
							BidDAO.insertBid(auctionItemID, userID, bidValue);

							AIB = AuctionItemDAO.getAuctionByID(auctionItemID);
							request.setAttribute("goToBean", AIB);
							dispatcher = request.getRequestDispatcher(url);
						} else {
							throw new NumberFormatException(); // So you are send to the
																// catch error
						}
					}
				} else {
					throw new NumberFormatException(); // So you are send to the
														// catch error
				}
			} catch (NumberFormatException e) {
				request.setAttribute("goToBean", AIB);
				dispatcher = request.getRequestDispatcher(response
						.encodeURL(url + "?error=numberNotValidError"));
			}
		}
		if (dispatcher != null) {
			dispatcher.forward(request, response);
		}

	}

	/**
	 * Handles the creation of a new acution Item
	 * 
	 * @param request
	 * @param response
	 * @throws ServletException
	 * @throws IOException
	 */
	private void handleNewAuction(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		RequestDispatcher dispatcher = null;

		String titleName = request.getParameter("titleName");
		String description = request.getParameter("description");

		String url = "";
		String errorUrl = "/WEB-INF/new-auction.jsp?error=";

		if (titleName.length() == 0 || titleName.length() > 80) {
			url = errorUrl + "titleLength";
		} else if (description.length() == 0 || description.length() > 8000) {
			url = errorUrl + "descriptionLength";
		} else {
			int price = -1;
			try {
				price = Integer.parseInt(request.getParameter("startPrice"));
			} catch (NumberFormatException e) {
				url = errorUrl + "numberFormat";
			}
			if (price >= 0) {
				int userID = (Integer) request.getSession().getAttribute(
						"userID");

				AuctionItemDAO.insertNewAuction(titleName, price, description,
						userID);
				AuctionItemBean aib = AuctionItemDAO
						.getNewestAuctionFromOwner(userID);

				request.setAttribute("goToBean", aib);
				url = "/WEB-INF/auction-item.jsp";
			}
		}
		dispatcher = request.getRequestDispatcher(url);
		dispatcher.forward(request, response);
	}

	/**
	 * Handles the deleting of auction items
	 * 
	 * @param request
	 * @param response
	 * @throws ServletException
	 * @throws IOException
	 */
	private void handleDelete(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {

		int AID = Integer.parseInt(request.getParameter("AID"));
		AuctionItemBean toBeDeleted = AuctionItemDAO.getAuctionByID(AID);
		int userID = (Integer) request.getSession().getAttribute("userID");

		if (userID == toBeDeleted.getUserID()) {
			AuctionItemDAO.deleteAuctionByAuctionID(AID);
		}
		handleSearch(request, response);

	}

	/**
	 * Handles the editing auctions.
	 * @param request
	 * @param response
	 * @throws ServletException
	 * @throws IOException
	 */
	private void handleEdit(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		RequestDispatcher dispatcher = null;

		String titleName = request.getParameter("titleName");
		String description = request.getParameter("description");
		int auctionID = Integer.parseInt(request.getParameter("auctionItemID"));

		String errorUrl = "/WEB-INF/auction-edit.jsp?error=";
		String url = "";
		
		boolean error = false;

		if (titleName.length() == 0 || titleName.length() > 80) {
			error = true;
			url = errorUrl + "titleLength";
		} else if (description.length() == 0 || description.length() > 8000) {
			error = true;
			url = errorUrl + "descriptionLength";
		} else {
			AuctionItemDAO.updateAuctionByID(titleName, description, auctionID);
			url = "/WEB-INF/searchbar.jsp?searchTarget=my-auctions&defaultMyAuctionContent=my-auctions";
		}
		
		if (error == true) {
			request.setAttribute("titleName", titleName);
			request.setAttribute("description", description);
			request.setAttribute("auctionItemID", auctionID);
		}
		dispatcher = request.getRequestDispatcher(url);
		dispatcher.forward(request, response);
	}

	/**
	 * Adds the the yourTopBid to a bid Bean
	 * @param AIB
	 * @param userID
	 * @return {@link BidBean}
	 */
	private BidBean getTopBidOfOwnerFromAuctionItem(AuctionItemBean AIB, int userID) {
		if (AIB.getTopBid().getBidUserID() != userID) {
			BidBean yourTopBid = new BidBean();
			yourTopBid.setBidValue(-1);
			for (BidBean bid : AIB.getBids()) {
				if (bid.getBidUserID() == userID
						&& bid.getBidValue() > yourTopBid.getBidValue()) {
					yourTopBid = bid;
				}
			}
			if (yourTopBid.getBidValue() > 0) {
				return yourTopBid;
			}
			return null; // if you haven't made a bid on this item.
		} else {
			return AIB.getTopBid();
		}
	}
}